// File: jmcomic-core/src/main/java/dev/jukomu/common/base/mapper/AbstractDictMapper.java
package dev.jukomu.common.base.mapper;

import java.io.IOException;
import java.util.*;

/**
 * 对应Python的AbstractDictMapper，为基于Map的Mapper提供通用实现。
 *
 * @param <K> 键的类型
 * @param <V> 值的类型
 */
public abstract class AbstractDictMapper<K, V> implements Mapper<K, V> {

    protected Map<K, V> data;

    public AbstractDictMapper() {
        this.data = null; // 延迟加载
    }

    @Override
    public void set(K key, V value, boolean save) throws IOException {
        makeSureLoaded();
        data.put(key, value);
        if (save) {
            save();
        }
    }

    @Override
    public V get(K key, V defaultValue) {
        makeSureLoaded();
        return data.getOrDefault(key, defaultValue);
    }

    @Override
    public boolean containsKey(K key) {
        makeSureLoaded();
        return data.containsKey(key);
    }

    @Override
    public void remove(K key, boolean save) throws IOException {
        makeSureLoaded();
        if (data.containsKey(key)) {
            data.remove(key);
            if (save) {
                save();
            }
        }
    }

    @Override
    public int size() {
        makeSureLoaded();
        return data.size();
    }

    @Override
    public void setData(Map<K, V> data) {
        this.data = data;
    }

    @Override
    public Map<K, V> getData() {
        makeSureLoaded();
        return data;
    }

    @Override
    public void clearData() {
        this.data = new HashMap<>();
    }

    @Override
    public void makeSureLoaded() {
        if (data == null) {
            try {
                load();
            } catch (IOException e) {
                // Wrap IOException into a RuntimeException as makeSureLoaded doesn't declare it.
                // Or, if load() is part of the API, makeSureLoaded() should also throw IOException.
                // For now, we'll assume IOExceptions during loading are critical and should be wrapped.
                throw new RuntimeException("Failed to load mapper data.", e);
            }
        }
    }

    @Override
    public Iterator<Map.Entry<K, V>> iterator() {
        makeSureLoaded();
        return data.entrySet().iterator();
    }

    @Override
    public Set<Map.Entry<K, V>> entrySet() {
        makeSureLoaded();
        return data.entrySet();
    }

    @Override
    public Set<K> keySet() {
        makeSureLoaded();
        return data.keySet();
    }

    @Override
    public Collection<V> values() {
        makeSureLoaded();
        return data.values();
    }

    @Override
    public String toString() {
        return "AbstractDictMapper{" +
                "size=" + size() +
                ", loaded=" + (data != null) +
                '}';
    }
}